﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using vJine.Core;
using vJine.Core.Base;
using vJine.Core.IoC;
using vJine.Core.ORM;

namespace vJine.Core.Web
{
    internal class HeaderAttribute : Attribute
    {

    }

    internal class ClientHeaderAttribute : HeaderAttribute
    {

    }

    internal class ServerHeaderAttribute : HeaderAttribute
    {

    }

    public partial class HttpBase
    {
        #region Init Headers

        public static readonly Dictionary<string, HttpHeader> ClientHeaders = new Dictionary<string, HttpHeader>();
        public static readonly Dictionary<string, HttpHeader> ServerHeaders = new Dictionary<string, HttpHeader>();

        public static TreeMap headerClient = new TreeMap();
        public static TreeMap headerServer = new TreeMap();

        static void InitHeaders()
        {
            HttpBase._InitHeaders(HttpBase.ClientHeaders, typeof(ClientHeaderAttribute));
            HttpBase._InitHeaders(HttpBase.ServerHeaders, typeof(ServerHeaderAttribute));

            HttpBase._InitHeaders(HttpBase.headerClient, typeof(ClientHeaderAttribute));
            HttpBase._InitHeaders(HttpBase.headerServer, typeof(ServerHeaderAttribute));
        }

        static void _InitHeaders(TreeMap Container, Type tAttribute)
        {
            List<PropertyInfo> Headers = Reflect.GetPropertiesByAttribute<HttpBase>(tAttribute);
            for (int i = 0; i < Headers.Count; i++)
            {
                string name = Headers[i].Name.Replace("_", "-");
                string Name = Headers[i].Name;

                Container.Create(
                    HttpBase.ASCII.GetBytes(name.ToLower()),
                    new HttpHeader()
                    {
                        Name = name + ":",
                        Get = Property<HttpBase, string>.Get(Name),
                        Set = Property<HttpBase, string>.Set(Name)
                    });
            }
        }

        static void _InitHeaders(Dictionary<string, HttpHeader> Container, Type tAttribute)
        {
            List<PropertyInfo> Headers = Reflect.GetPropertiesByAttribute<HttpBase>(tAttribute);
            for (int i = 0; i < Headers.Count; i++)
            {
                string name = Headers[i].Name.Replace("_", "-");
                string Name = Headers[i].Name;
                Container.Add(name.ToLower(),
                    new HttpHeader()
                    {
                        Name = name + ": ",
                        Get = Property<HttpBase, string>.Get(Name),
                        Set = Property<HttpBase, string>.Set(Name)
                    }
                        );
            }
        }

        public void set(string header)
        {
            string[] H = header.Split(':');
            string key = H[0].ToLower().Replace("-", "_"), value = H[1];

            key = key.ToLower().Replace("_", "-");
            if (HttpBase.ServerHeaders.ContainsKey(key))
            {
                HttpBase.ServerHeaders[key].Set(this, value);
            }
            else
            {
                this.Unkonwns.Add(header);
            }
        }

        public string get(string key)
        {
            key = key.ToLower().Replace("_", "-");
            if (HttpBase.ServerHeaders.ContainsKey(key))
            {
                return HttpBase.ServerHeaders[key].Get(this);
            }

            return null;
        }
        #endregion Init Headers

        #region Headers
        public List<string> Unkonwns { get; protected set; }

        public class HttpHeader
        {
            public string Name { get; set; }
            public GetSignature<HttpBase, string> Get { get; set; }
            public SetSignature<HttpBase, string> Set { get; set; }
        }

        [ClientHeader]
        public string Host { get; set; }
        [ClientHeader]
        public string User_Agent { get; set; }
        [ClientHeader]
        public string Referer { get; set; }

        [ClientHeader]
        public string Accept { get; set; }
        [ClientHeader]
        public string Accept_Charset { get; set; }
        [ClientHeader]
        public string Accept_Encoding { get; set; }
        [ClientHeader]
        public string Accept_Language { get; set; }
        [ClientHeader]
        public string Authorization { get; set; }
        [ClientHeader]
        public string Cookie { get; set; }
        [ClientHeader]
        public string Expect { get; set; }
        [ClientHeader]
        [ServerHeader]
        public string Content_Length { get; set; }
        [ClientHeader]
        [ServerHeader]
        public string Content_Type { get; set; }
        [ServerHeader]
        public string Content_Disposition { get; set; }
        [ServerHeader]
        public string Content_Description { get; set; }
        [ClientHeader]
        public string From { get; set; }
        [ClientHeader]
        public string If_Match { get; set; }
        [ClientHeader]
        public string If_None_Match { get; set; }
        [ClientHeader]
        public string If_Modified_Since { get; set; }
        [ClientHeader]
        public string If_Unmodified_Since { get; set; }
        [ClientHeader]
        public string If_Range { get; set; }
        [ClientHeader]
        public string Range { get; set; }
        [ClientHeader]
        public string Max_Forwards { get; set; }
        [ClientHeader]
        public string Proxy_Authrization { get; set; }
        [ClientHeader]
        [ServerHeader]
        public string Pragma { get; set; }
        [ClientHeader]
        public string TE { get; set; }
        [ClientHeader]
        public string Cache_Control { get; set; }

        [ServerHeader]
        public string Date { get; set; }
        [ServerHeader]
        public string Server { get; set; }
        [ServerHeader]
        public string Accept_Ranges { get; set; }
        [ServerHeader]
        public string Age { get; set; }
        [ServerHeader]
        public string Proxy_Authenticate { get; set; }
        [ServerHeader]
        public string Retry_After { get; set; }
        [ServerHeader]
        public string Etag { get; set; }
        [ServerHeader]
        public string Location { get; set; }
        [ServerHeader]
        public string Via { get; set; }
        [ServerHeader]
        public string Waring { get; set; }
        [ServerHeader]
        public string Trailer { get; set; }
        [ServerHeader]
        public string Transfer_Encoding { get; set; }
        [ClientHeader]
        [ServerHeader]
        public string Upgrade { get; set; }
        [ClientHeader]
        [ServerHeader]
        public string Connection { get; set; }

        Dictionary<string, string> Cookies = new Dictionary<string, string>();
        [ServerHeader]
        public string Set_Cookie
        {
            get
            {
                StringBuilder sbCookies = new StringBuilder();
                int Counter = 0;
                int LastCount = this.Cookies.Count - 1;
                foreach (KeyValuePair<string, string> kv in this.Cookies)
                {
                    if (Counter > 0)
                    {
                        sbCookies.Append("Set-Cookie: ");
                    }
                    sbCookies.Append(kv.Value);
                    if (Counter < LastCount)
                    {
                        sbCookies.Append("\r\n");
                    }
                    Counter += 1;
                }

                if (sbCookies.Length == 0)
                {
                    return null;
                }
                else
                {
                    string Cookie = sbCookies.ToString();
                    sbCookies.Remove(0, sbCookies.Length);
                    sbCookies = null;

                    return Cookie;
                }
            }
            set
            {
                if (value == null)
                {
                    this.Cookies.Clear();
                    return;
                }

                string Key = value.Substring(0, value.IndexOf('='));
                if (this.Cookies.ContainsKey(Key))
                {
                    this.Cookies[Key] = value;
                }
                else
                {
                    this.Cookies.Add(Key, value);
                }
            }
        }

        [ServerHeader]
        public string Allow { get; set; }
        [ServerHeader]
        public string Content_Encoding { get; set; }
        [ServerHeader]
        public string Content_Language { get; set; }
        [ServerHeader]
        public string Content_Locatoin { get; set; }
        [ServerHeader]
        public string Content_MD5 { get; set; }
        [ServerHeader]
        public string Content_Range { get; set; }
        [ServerHeader]
        public string Expires { get; set; }
        [ServerHeader]
        public string Last_Modified { get; set; }
        [ServerHeader]
        public string X_Powered_By { get; set; }
        [ServerHeader]
        public string WWW_Authenticate { get; set; }
        [ServerHeader]
        public string Vary { get; set; }
        [ClientHeader]
        public string X_Requested_With { get; set; }

        //http://tools.ietf.org/html/rfc6455
        [ClientHeader]
        public string Sec_WebSocket_Key { get; set; }
        [ClientHeader]
        public string Sec_WebSocket_Version { get; set; }
        [ClientHeader]
        public string Sec_WebSocket_Protocol { get; set; }
        [ClientHeader]
        public string Sec_WebSocket_Extensions { get; set; }
        [ClientHeader]
        public string Origin { get; set; }
        [ServerHeader]
        public string Sec_WebSocket_Accept { get; set; }
        #region CROSS ORIGIN
        [ClientHeader]
        public string Access_Control_Request_Method { get; set; }
        [ClientHeader]
        public string Access_Control_Request_Headers { get; set; }

        [ServerHeader]
        public string Access_Control_Allow_Origin { get; set; }
        [ServerHeader]
        public string Access_Control_Allow_Credentials { get; set; }
        [ServerHeader]
        public string Access_Control_Expose_Headers { get; set; }
        [ServerHeader]
        public string Access_Control_Max_Age { get; set; }
        [ServerHeader]
        public string Access_Control_Allow_Methods { get; set; }
        [ServerHeader]
        public string Access_Control_Allow_Headers { get; set; }
        #endregion CROSS ORIGIN
        #endregion Headers
    }
}
